<?php

namespace App\Services\Order;

use App\Jobs\CancelSkuOperationStatisticsJob;
use App\Models\AfterSaleOrder;
use App\Models\AgentRevenue;
use App\Models\CommodityActivity;
use App\Models\Order;
use Carbon\Carbon;
use Illuminate\Queue\SerializableClosure;
use Symfony\Component\HttpKernel\Exception\HttpException;

class CancelOrder extends OperationBase
{
    private $statusCancelType;

    private $statusCancelOperatorId;

    public function __construct($statusCancelOperatorId = 0, $statusCancelType = Order::CANCEL_TYPE_AGENT)
    {
        $this->statusCancelType = $statusCancelType;
        $this->statusCancelOperatorId = $statusCancelOperatorId;
    }

    /**
     * @param Order $order
     */
    public function beforeHandle($order = null)
    {
        $allowCancelWithAdmin = false; // 是否允许后台取消
        if ($this->statusCancelType === Order::CANCEL_TYPE_ADMIN) {
            // 后台操作时,允许在已发货的情况下(但是没有售后订单)取消
            $isExistsAfterSaleOrder = $order->afterSaleOrder()
                ->whereIn('status', [
                    AfterSaleOrder::STATUS_PENDING_REVIEW,
                    AfterSaleOrder::STATUS_FOLLOWING_UP,
                    AfterSaleOrder::STATUS_PASSED
                ])
                ->exists();
            if ($isExistsAfterSaleOrder) {
                abort(400, '订单已有售后订单,无法取消');
            }

            $allowCancelWithAdmin = in_array($order->status, [Order::STATUS_TO_BE_DELIVERED, Order::STATUS_SHIPPED], true);
        }

        if ($order->status !== Order::STATUS_TO_BE_DELIVERED && !$allowCancelWithAdmin) {
            if ($order->status === Order::STATUS_SHIPPED) {
                abort(400, '订单已发货,无法取消');
            } elseif ($order->status === Order::STATUS_CANCELLED) {
                abort(400, '订单已取消,请勿重复操作');
            } else {
                abort(400, '订单未处于待发货状态,无法取消');
            }
        }

        if ((int) $order['settlement_status'] === Order::SETTLEMENT_STATUS_UNDONE) {
            abort(400, '订单结算中,请稍等片刻');
        }
    }

    public function handle($order = null)
    {
        if ($order->commodityActivity['locking'] === CommodityActivity::LOCKING_LOCKING && $this->statusCancelType !== Order::CANCEL_TYPE_ADMIN) {
            throw new HttpException(400, '商品活动已锁定,无法取消');
        }

        // 涉及的 SKU 以及数量
        $skuWithQuantity = [];
        foreach ($order->skus as $sku) {
            $skuWithQuantity[$sku['commodity_activity_sku_id']] = $sku['amount'];
        }
        dispatch_now(
            new CancelSkuOperationStatisticsJob(
                $skuWithQuantity,
                $order['id'],
                true,
                null,
                new SerializableClosure(function (Order $order) {
                    // 退回运费
                    $order->freight_balance_paid > 0 && $order->agent->incrementOrDecrementBalance($order->freight_balance_paid, AgentRevenue::TYPE_CANCEL_ORDER_FREIGHT, $order);
                    $order->freight_unextractable_balance_paid > 0 && $order->agent->incrementOrDecrementBalance($order->freight_unextractable_balance_paid, AgentRevenue::TYPE_CANCEL_ORDER_FREIGHT_UNEXTRACTABLE, $order);

                    // 已取消状态
                    $order->update([
                        'status' => Order::STATUS_CANCELLED,
                        'status_cancel_type' => $this->statusCancelType,
                        'status_cancel_operator_id' => $this->statusCancelOperatorId,
                        'cancel_time' => Carbon::now(),
                        'freight' => 0,
                        'freight_balance_paid' => 0,
                        'freight_unextractable_balance_paid' => 0,
                    ]);
                })
            ));
    }
}
